/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package thread;

/**
 *
 * @author PyyPyLyn
 */

import DLL.*;
import java.io.File;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.swing.*;


public class Download_Thread extends Thread
{
    String FileName;
    JTable jTable1;
    JLabel lbGoiTin;
    private byte[] bdatare = new byte[1024];
    List<byte[]> arraybytes;
    InitializationBroadCastGroup b_Group;

    public Download_Thread(String filename, JTable dt, InitializationBroadCastGroup group, JLabel lb)
    {
        FileName = filename;
        jTable1 = dt;
        b_Group = group;
        lbGoiTin = lb;
    }
    
    public void run()
    {
        if(FileName == null)
        {
            JOptionPane.showMessageDialog(null, "Chưa có tên tập cần tải !");
            return;
        }
        /// lập danh sách các chunk          
        int chunksCount = jTable1.getRowCount();
        ArrayList[] listchunks = new ArrayList[chunksCount];
        for (int i = 0; i < chunksCount; i++)
        {
            listchunks[i] = new ArrayList();
        }        
        
        QueryPackets qp = new QueryPackets("1", FileName);
        byte[] buf = QueryPackets.SendNormal(qp.getFlag(), qp.getData());
        try
        {
            boolean result = SendFunction.SendBroadCastPacket(b_Group.getM_Group(),b_Group.getGroup(),buf);
            
            DatagramSocket d_Socket = new DatagramSocket(4447);
            byte[] data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data, data.length);
            
            while(true)
            {
                d_Socket.setSoTimeout(1000);
                d_Socket.receive(packet);
                String PacketIP = packet.getAddress().getHostAddress();
                lbGoiTin.setText("Đã Nhận Gói Tin Phản Hồi");    

                /// phân tích gói tin
                List<String> chunks = ResponseFunction.PhanTichGoiTinPhanHoi(packet);

                // Làm list
                for (int i = 0; i < chunks.size(); i++)
                {
                    int index = Integer.parseInt(chunks.get(i));
                    listchunks[index - 1].add(PacketIP);
                }
            }
        }
        catch(Exception e)
        {  
               
        }
        //ArrayList<DatagramPacket> listData = new ArrayList<DatagramPacket>();
        
        int b =0;   
        List<Thread> threads = new ArrayList<Thread>();
        for (int i = 0; i < listchunks.length ;i++)
        {     
//            List<ReceivedData> redata = new ArrayList<ReceivedData>();
//            DatagramSocket dl_Socket = null;
//            DatagramSocket socket_requestdownload;
            InetAddress add = null;
//            boolean result = false;
//            arraybytes = new ArrayList<byte[]>();  
            String chunkname = FileName + "." + (i+1)+".chunk";
            File fchunk = new File(".\\"+chunkname);
            if(!fchunk.exists())
            {    
            try
            {                   
//                dl_Socket = new DatagramSocket();
//                socket_requestdownload = new DatagramSocket();
                Random rad = new Random();
                String ip = listchunks[i].get(rad.nextInt(listchunks[i].size())).toString();
                add = InetAddress.getByName(ip);                             
                                
//                result = SendFunction.SendRequestDownload(socket_requestdownload, add, chunkname, dl_Socket.getLocalPort());
//                dl_Socket.setSoTimeout(2000);
            }
            catch(Exception ex)
            {
                System.out.println("error");
            }         
            Download_Core dc = new Download_Core(chunkname, add, threads);
            dc.start();
            threads.add(dc);
            
            try
            {
                dc.join();
            }
            catch (Exception ex)
            {
            
            }
//            if (result == true)
//            {
//                //JOptionPane.showMessageDialog(null, "Port download da mo!");
//                lbGoiTin.setText(""+dl_Socket.getLocalPort());
//            } 
            
            
//            int sizedata = 0;
//            int a = 0;
//            
//            byte[] response = "4".getBytes();
//            DatagramPacket rs_Pkt = new DatagramPacket(response, response.length, add, 4449);
//            DatagramSocket rs_Socket = null;
//            try
//            {
//                rs_Socket = new DatagramSocket();
//            }
//            catch (Exception ex)
//            {
//            
//            }
//            
//            while(true)
//            { 
//                byte[] packet = new byte[1024];
//                DatagramPacket packet_Data;
//                try
//                {        
//                    packet_Data = new DatagramPacket(packet, packet.length);
//                    dl_Socket.receive(packet_Data);                    
//                
//                    a++;
//                    if(packet_Data.getData()[0] != 0)
//                    {
//                        if(a==532)
//                        { 
//                            arraybytes.add(packet);
//                        }
//                        else
//                        {   
//                            arraybytes.add(packet);
//                        }
//                        lbGoiTin.setText(""+a);  
//                        try
//                        {
//                            rs_Socket.send(rs_Pkt);
//                        }
//                        catch(Exception ex)
//                                {}
//                    }
//                    else
//                    {
//                        break;
//                    }
//                }
//                catch(Exception ex)
//                {           
//                    int count = arraybytes.size();
//                    if(count > 0)
//                    {
//                        for(int c = 0; c < count; c++)
//                        {
//                            byte[] vData = (byte[]) arraybytes.get(c);
//                            byte flags = vData[0];
//
//                            byte[] headerlength = Arrays.copyOfRange(vData, 1, 3);
//                            short valueHeaderlength = ByteBuffer.wrap(headerlength).order(ByteOrder.LITTLE_ENDIAN).getShort();
//                            //String Header
//                            byte[] header = Arrays.copyOfRange(vData, 17, 17+valueHeaderlength);
//                            String valueHeader = new String(header);
//                            String fileName = valueHeader;
//                            if(fileName.equals(chunkname))
//                            {
//                                //Short packet length
//                                byte[] packets = Arrays.copyOfRange(vData, 3, 5);
//                                short valuePackets = ByteBuffer.wrap(packets).order(ByteOrder.LITTLE_ENDIAN).getShort();
//                                //Integer CheckSum
//                                byte[] checksum = Arrays.copyOfRange(vData, 5, 9);
//                                int valueChecksum = ((checksum[0] & 0xFF) << 24) | ((checksum[1] & 0xFF) << 16)
//                                       | ((checksum[2] & 0xFF) << 8) | (checksum[3] & 0xFF);
//                                //Integer Sequence
//                                byte[] sequence = Arrays.copyOfRange(vData, 9, 13);
//                                int valuesequence = ((sequence[0] & 0xFF) << 24) | ((sequence[1] & 0xFF) << 16)
//                                        | ((sequence[2] & 0xFF) << 8) | (sequence[3] & 0xFF);
//                                //Integer Acknowledge
//                                byte[] acknowledge = Arrays.copyOfRange(vData, 13, 17);
//                                int valueacknowledge = ((acknowledge[0] & 0xFF) << 24) | ((acknowledge[1] & 0xFF) << 16)
//                                        | ((acknowledge[2] & 0xFF) << 8) | (acknowledge[3] & 0xFF);
//
//                                //ByteData
//                                byte[] data = Arrays.copyOfRange(vData, 17+valueHeaderlength, 17+valueHeaderlength+valuePackets);
//                                int Ischecksum = (int)CommonMethods.calculateChecksum(data);
//                                if(true)
//                                {
//                                    ReceivedData rdata = new ReceivedData(data, valuesequence, valueacknowledge);
//                                    redata.add(rdata);                       
//                                    sizedata+=data.length;
//
//                                }
//                            }
//                        }
//                        redata = CommonMethods.SortReceivedData(redata);
//                        byte[] endByte = new byte[sizedata];
//                        int abc = 0;
//                        for(int c=0;c<redata.size();c++)
//                        {
//                            for(int e = 0; e<redata.get(c).data.length; e++)
//                            {
//                                if(abc == 985)
//                                {
//                                    int f = 0;
//                                    f = 1;
//                                }
//                                endByte[abc] = redata.get(c).data[e];
//                                abc++;                    
//                            }
//                            //endByte = Arrays.copyOfRange(redata.get(c).data, abc, abc+redata.get(c).data.length);
//
//                        }
//                        CommonMethods.ConvertByteArrayIntoFile(endByte,"1"+chunkname);
//                    }
//                    rs_Socket.close();                    
//                    break;
//                }                
//            }
        } 
        }
        
        int count = threads.size();
        for(int i = 0; i < count; i++)
        {
            if(threads.get(i).isAlive())
            {
                i = i - 1;
            }
        }
//        for(int i = 0; i < threads.size(); i++)
//        {
//            try
//            {
//                threads.get(i).join();
//            }
//            catch(Exception ex)
//            {
//            
//            }
//        }
        File folder = new File(".");
        File[] files = folder.listFiles();
        List<File> chunkFiles = new ArrayList<File>();
        for(int i = 0; i < files.length; i++)
        {
            if(files[i].getName().startsWith(FileName))
            {
                chunkFiles.add(files[i]);
            }
        }
        if(chunkFiles.size() == chunksCount)
        {
            files = new File[chunksCount];
            chunkFiles.toArray(files);
            CommonMethods.JoinFilesIntoOrigionalFile(files);
        }

    }

    /**
     * @return the bdatare
     */
    public byte[] getBdatare() {
        return bdatare;
    }

    /**
     * @param bdatare the bdatare to set
     */
    public void setBdatare(byte[] bdatare) {
        this.bdatare = bdatare;
    }
}
    

